﻿using System;
using System.Collections.Generic;
using System.Linq;
using DosTexPrj.Core.Models;
using DosTexPrj.Core.RepositoriesInterface;
using NUnit.Framework;

namespace DosTexPrj.Implement.NHibernate.Test.Repositories
{
    [TestFixture]
    public class TestSupplierYarnOrder : RepositoryFixtureBase
    {
        private IRepository _repository;
        private DeliveryMethod _deliveryMethod;
        private PaymentMethod _paymentMethod;
        private Composition _composition;
        private OrderStatus _orderStatus;

        protected override void Context()
        {
            this._repository = MyServiceLocator.DoGetInstance<IRepository>();
            this._deliveryMethod = this._repository.FindByKey<DeliveryMethod>(1);
            this._paymentMethod = this._repository.FindByKey<PaymentMethod>(1);
            this._composition = this._repository.FindByKey<Composition>(1);
            this._orderStatus = this._repository.FindByKey<OrderStatus>(1);
        }

        [Test]
        public void Can_Create_Supplier()
        {
            var supplier = this.CreateDummySupplier();
            supplier = this._repository.Save<Supplier>(supplier);
            Assert.IsTrue(supplier != null && supplier.Id > 0);
        }

        [Test]
        public void Can_Create_New_Supplier_YarnOrder_YarnOrderDetail()
        {
            //Create Order
            var customer = this.CreateDummyCustomer();
            customer = this._repository.Save<Customer>(customer);
            var order = this.CreateDummyOrder(customer);
            order = this._repository.Save<Order>(order);

            //Create YarnOrder
            var supplier = this.CreateDummySupplier();
            var yarnOrder = this.CreateDummyYarnOrder(supplier, order);
            var yarnOrderDetails = this.CreateDummyYarnOrderDetails(yarnOrder);
            yarnOrder.YarnOrderDetails = yarnOrderDetails;
            supplier.YarnOrders.Add(yarnOrder);
            supplier = this._repository.Save<Supplier>(supplier);

            yarnOrder = supplier.YarnOrders[0];
            yarnOrderDetails = yarnOrder.YarnOrderDetails;

            Assert.IsTrue(supplier != null && supplier.Id > 0
                            && supplier.YarnOrders != null && supplier.YarnOrders.Count > 0
                            && yarnOrder.Id > 0 && yarnOrder.BelongToOrder.Id == order.Id
                            && yarnOrderDetails != null && yarnOrderDetails.Count > 0);
        }

        [Test]
        public void Can_Create_New_YarnOrder_YarnOrderDetail()
        {
            //Create Order
            var customer = this.CreateDummyCustomer();
            customer = this._repository.Save<Customer>(customer);
            var order = this.CreateDummyOrder(customer);
            order = this._repository.Save<Order>(order);

            //Create YarnOrder
            var supplier = this.CreateDummySupplier();
            supplier = this._repository.Save<Supplier>(supplier);
            var yarnOrder = this.CreateDummyYarnOrder(supplier, order);
            var yarnOrderDetails = this.CreateDummyYarnOrderDetails(yarnOrder);
            yarnOrder.YarnOrderDetails = yarnOrderDetails;
            yarnOrder = this._repository.Save<YarnOrder>(yarnOrder);

            Assert.IsTrue(yarnOrder != null && yarnOrder.Id > 0
                            && yarnOrder.BelongToOrder == order
                            && yarnOrder.Supplier == supplier
                            && yarnOrder.YarnOrderDetails != null && yarnOrder.YarnOrderDetails.Count > 0);
        }

        [Test]
        public void Can_Edit_Supplier()
        {
            var supplier = this.CreateDummySupplier();
            supplier = this._repository.Save<Supplier>(supplier);
            supplier.SupplierName = "EditSupplier";
            supplier = this._repository.Save<Supplier>(supplier);
            Assert.IsTrue(supplier != null && supplier.SupplierName.Equals("EditSupplier"));
        }

        [Test]
        public void Can_Edit_YarnOrder_AddNewDetail()
        {
            //Create Order
            var customer = this.CreateDummyCustomer();
            customer = this._repository.Save<Customer>(customer);
            var order = this.CreateDummyOrder(customer);
            order = this._repository.Save<Order>(order);

            var supplier = this.CreateDummySupplier();
            supplier = this._repository.Save<Supplier>(supplier);
            var yarnOrder = this.CreateDummyYarnOrder(supplier, order);
            var yarnOrderDetails = this.CreateDummyYarnOrderDetails(yarnOrder);
            yarnOrder.YarnOrderDetails = yarnOrderDetails;
            yarnOrder = this._repository.Save<YarnOrder>(yarnOrder);
            yarnOrder.IsDeliveredBefore = true;
            yarnOrder.YarnOrderDetails.Add(new YarnOrderDetail
            {
                Price = Math.Round(300d, 2),
                QuantityOfBox = 30,
                Weigth = Math.Round(300d, 2),
                Composition = _composition
            });
            yarnOrder = this._repository.Save<YarnOrder>(yarnOrder);
            Assert.IsTrue(yarnOrder != null && yarnOrder.IsDeliveredBefore == true
                            && yarnOrder.YarnOrderDetails != null && yarnOrder.YarnOrderDetails.Count == 4);
        }

        [Test]
        public void Can_Delete_Detail_For_Yarn_Order()
        {
            //Create Order
            var customer = this.CreateDummyCustomer();
            customer = this._repository.Save<Customer>(customer);
            var order = this.CreateDummyOrder(customer);
            order = this._repository.Save<Order>(order);

            var supplier = this.CreateDummySupplier();
            supplier = this._repository.Save<Supplier>(supplier);
            var yarnOrder = this.CreateDummyYarnOrder(supplier, order);
            var yarnOrderDetails = this.CreateDummyYarnOrderDetails(yarnOrder);
            yarnOrder.YarnOrderDetails = yarnOrderDetails;
            yarnOrder = this._repository.Save<YarnOrder>(yarnOrder);
            this._repository.Delete<YarnOrderDetail>(x => x.YarnOrder == yarnOrder);
            yarnOrderDetails = this._repository.FindByCondition<YarnOrderDetail>(x => x.YarnOrder == yarnOrder).ToList();
            Assert.IsTrue(yarnOrderDetails == null || yarnOrderDetails.Count == 0);
        }

        [Test]
        public void Can_Delete_YarnOrder()
        {
            //Create Order
            var customer = this.CreateDummyCustomer();
            customer = this._repository.Save<Customer>(customer);
            var order = this.CreateDummyOrder(customer);
            order = this._repository.Save<Order>(order);

            var supplier = this.CreateDummySupplier();
            var yarnOrder = this.CreateDummyYarnOrder(supplier, order);
            var yarnOrderDetails = this.CreateDummyYarnOrderDetails(yarnOrder);
            yarnOrder.YarnOrderDetails = yarnOrderDetails;
            supplier.YarnOrders.Add(yarnOrder);
            supplier = this._repository.Save<Supplier>(supplier);

            this._repository.Delete<YarnOrder>(x => x.Supplier.Id == supplier.Id);
            yarnOrder = this._repository.FindByKey<YarnOrder>(yarnOrder.Id);
            Assert.IsNull(yarnOrder);
        }

        [Test]
        public void Can_Delete_Supplier()
        {
            //Create Order
            var customer = this.CreateDummyCustomer();
            customer = this._repository.Save<Customer>(customer);
            var order = this.CreateDummyOrder(customer);
            order = this._repository.Save<Order>(order);

            var supplier = this.CreateDummySupplier();
            var yarnOrder = this.CreateDummyYarnOrder(supplier, order);
            var yarnOrderDetails = this.CreateDummyYarnOrderDetails(yarnOrder);
            yarnOrder.YarnOrderDetails = yarnOrderDetails;
            supplier.YarnOrders.Add(yarnOrder);
            supplier = this._repository.Save<Supplier>(supplier);
            this._repository.Delete<Supplier>(x => x.Id == supplier.Id);
            supplier = this._repository.FindByKey<Supplier>(supplier.Id);
            Assert.IsNull(supplier);
        }

        #region --- Private methods ---

        private Customer CreateDummyCustomer()
        {
            return new Customer { Address = "address", CustomerName = "customername", PhoneNumber = "phonenumber" };
        }

        private Order CreateDummyOrder(Customer customer)
        {
            return new Order
            {
                Freight = "freight",
                Customer = customer,
                DeliveryDate = DateTime.Today.AddDays(7),
                DeliveryMethod = _deliveryMethod,
                IsDeliveredBefore = false,
                OrderDate = DateTime.Today,
                OrderStatus = _orderStatus,
                PaymentMethod = _paymentMethod,
            };
        }

        private Supplier CreateDummySupplier()
        {
            return new Supplier
            {
                Address = "Supplier address dummy",
                SupplierName = "Supplier name dummy",
                Phone = "123456"
            };
        }

        private YarnOrder CreateDummyYarnOrder(Supplier supplier, Order order)
        {
            return new YarnOrder
            {
                DeliveryAddress = String.Format("Dummy DeliveryAddress {0}", DateTime.Now.ToString()),
                DeliveryDate = DateTime.Today.AddDays(10),
                DeliveryMethod = _deliveryMethod,
                IsDeliveredBefore = false,
                NumberOfDateExtensionDelivery = 15,
                OrderDate = DateTime.Today,
                OrderStatus = _orderStatus,
                PaymentMethod = _paymentMethod,
                Supplier = supplier,
                BelongToOrder = order
            };
        }

        private IList<YarnOrderDetail> CreateDummyYarnOrderDetails(YarnOrder yarnOrder)
        {
            var yarnOrderDetails = new List<YarnOrderDetail>();
            for (int i = 0; i < 3; i++)
            {
                yarnOrderDetails.Add(new YarnOrderDetail
                {
                    Price = Math.Round(100d, 2),
                    QuantityOfBox = 10,
                    Weigth = Math.Round(100d, 2),
                    YarnOrder = yarnOrder,
                    Composition = _composition
                });
            }
            return yarnOrderDetails;
        }

        #endregion --- Private methods ---
    }
}